Python

您所在的位置:网站首页 构造阶乘函数 python Python

Python

2023-03-26 00:35| 来源: 网络整理| 查看: 265

原项目地址:

Python-Core-50-Courses(https://hub.fastgit.org/jackfrued/Python-Core-50-Courses.git)

其他相关资源可参考

Python|Git remote|hosts|PyCharm常用快捷键|变量转换|命名|类型|运算符|分支|调整tab|循环:Python语言基础50课-学习记录(1)(https://zhuanlan.zhihu.com/p/614795004)

第12课:常用数据结构之字典

Python程序中的字典以键值对(键和值的组合)的方式把数据组织到一起,我们可以通过键找到与之对应的值并进行操作。

创建和使用字典

在Python中创建字典可以使用{}字面量语法,字典的{}中的元素是以键值对的形式存在的,每个元素由:分隔的两个值构成,:前面是键,:后面是值,代码如下所示。

xinhua = { '麓': '山脚下', '路': '道,往来通行的地方;方面,地区:南~货,外~货;种类:他俩是一~人', '蕗': '甘草的别名', '潞': '潞水,水名,即今山西省的浊漳河;潞江,水名,即云南省的怒江' } print(xinhua) person = { 'name': '王大锤', 'age': 55, 'weight': 60, 'office': '科华北路62号', 'home': '中同仁路8号', 'tel': '13122334455', 'econtact': '13800998877' } print(person)

也可以使用内置函数dict或者是字典的生成式语法来创建字典,代码如下所示。

# dict函数(构造器)中的每一组参数就是字典中的一组键值对 person = dict(name='王大锤', age=55, weight=60, home='中同仁路8号') print(person) # {'name': '王大锤', 'age': 55, 'weight': 60, 'home': '中同仁路8号'} # 可以通过Python内置函数zip压缩两个序列并创建字典 items1 = dict(zip('ABCDE', '12345')) print(items1) # {'A': '1', 'B': '2', 'C': '3', 'D': '4', 'E': '5'} items2 = dict(zip('ABCDE', range(1, 10))) print(items2) # {'A': 1, 'B': 2, 'C': 3, 'D': 4, 'E': 5} # 用字典生成式语法创建字典 items3 = {x: x ** 3 for x in range(1, 6)} print(items3) # {1: 1, 2: 8, 3: 27, 4: 64, 5: 125}

想知道字典中一共有多少组键值对,仍然是使用len函数;如果想对字典进行遍历,可以用for循环,但是需要注意,for循环只是对字典的键进行了遍历,不过没关系,在讲完字典的运算后,我们可以通过字典的键获取到和这个键对应的值。

person = {'name': '王大锤', 'age': 55, 'weight': 60, 'office': '科华北路62号'} print(len(person)) # 4 for key in person: print(key)字典的运算

对于字典类型来说,成员运算和索引运算肯定是最为重要的,前者可以判定指定的键在不在字典中,后者可以通过键获取对应的值或者向字典中加入新的键值对。值得注意的是,字典的索引不同于列表的索引,列表中的元素因为有属于自己有序号,所以列表的索引是一个整数;字典中因为保存的是键值对,所以字典的索引是键值对中的键,通过索引操作可以修改原来的值或者向字典中存入新的键值对。需要特别提醒大家注意的是,字典中的键必须是不可变类型,例如整数(int)、浮点数(float)、字符串(str)、元组(tuple)等类型的值;显然,列表(list)和集合(set)是不能作为字典中的键的,当然字典类型本身也不能再作为字典中的键,因为字典也是可变类型,但是字典可以作为字典中的值

person = {'name': '王大锤', 'age': 55, 'weight': 60, 'office': '科华北路62号'} # 检查name和tel两个键在不在person字典中 print('name' in person, 'tel' in person) # True False # 通过age修将person字典中对应的值修改为25 if 'age' in person: person['age'] = 25 # 通过索引操作向person字典中存入新的键值对 person['tel'] = '13122334455' person['signature'] = '你的男朋友是一个盖世垃圾,他会踏着五彩祥云去迎娶你的闺蜜' print('name' in person, 'tel' in person) # True True # 检查person字典中键值对的数量 print(len(person)) # 6 # 对字典的键进行循环并通索引运算获取键对应的值 for key in person: print(f'{key}: {person[key]}')

需要注意,在通过索引运算获取字典中的值时,如指定的键没有在字典中,将会引发KeyError异常。

字典的方法# 字典中的值又是一个字典(嵌套的字典) students = { 1001: {'name': '狄仁杰', 'sex': True, 'age': 22, 'place': '山西大同'}, 1002: {'name': '白元芳', 'sex': True, 'age': 23, 'place': '河北保定'}, 1003: {'name': '武则天', 'sex': False, 'age': 20, 'place': '四川广元'} } # 使用get方法通过键获取对应的值,如果取不到不会引发KeyError异常而是返回None或设定的默认值 print(students.get(1002)) # {'name': '白元芳', 'sex': True, 'age': 23, 'place': '河北保定'} print(students.get(1005)) # None print(students.get(1005, {'name': '无名氏'})) # {'name': '无名氏'} #1002存在,则按更新后的命令输出 print(students.get(1002, {'names': '无名氏'})) {'name': '白元芳', 'sex': True, 'age': 23, 'place': '河北保定'} print(students.get(1002)) {'name': '白元芳', 'sex': True, 'age': 23, 'place': '河北保定'} # 获取字典中所有的键 print(students.keys()) # dict_keys([1001, 1002, 1003]) # 获取字典中所有的值 print(students.values()) # dict_values([{...}, {...}, {...}]) # 获取字典中所有的键值对 print(students.items()) # dict_items([(1001, {...}), (1002, {....}), (1003, {...})]) # 对字典中所有的键值对进行循环遍历 for key, value in students.items(): print(key, '--->', value) # 使用pop方法通过键删除对应的键值对并将该值赋给stu1 stu1 = students.pop(1002) print(stu1) # {'name': '白元芳', 'sex': True, 'age': 23, 'place': '河北保定'} print(len(students)) # 2 # stu2 = students.pop(1005) # KeyError: 1005 stu2 = students.pop(1005, {}) print(stu2) # {} # 使用popitem方法删除字典中最后一组键值对并返回对应的二元组 # 如果字典中没有元素,调用该方法将引发KeyError异常 key, value = students.popitem() #popitem方法删除字典中最后一组键值对并返回对应的二元组 print(key, value) # 1003 {'name': '武则天', 'sex': False, 'age': 20, 'place': '四川广元'} # 如果这个键在字典中存在,setdefault返回原来与这个键对应的值 # 如果这个键在字典中不存在,向字典中添加键值对,返回第二个参数的值,默认为None result = students.setdefault(1005, {'name': '方启鹤', 'sex': True}) print(result) # {'name': '方启鹤', 'sex': True} print(students) # {1001: {...}, 1005: {...}} # 使用update更新字典元素,相同的键会用新值覆盖掉旧值,不同的键会添加到字典中 others = { 1005: {'name': '乔峰', 'sex': True, 'age': 32, 'place': '北京大兴'}, 1010: {'name': '王语嫣', 'sex': False, 'age': 19}, 1008: {'name': '钟灵', 'sex': False} } students.update(others) print(students) # {1001: {...}, 1005: {...}, 1010: {...}, 1008: {...}}

跟列表一样,从字典中删除元素也可以使用del关键字,在删除元素的时候如果指定的键索引不到对应的值,一样会引发KeyError异常,具体的做法如下所示。

person = {'name': '王大锤', 'age': 25, 'sex': True} del person['age'] print(person) # {'name': '王大锤', 'sex': True}字典的应用及生成式语法

我们通过几个简单的例子来讲解字典的应用。

例子1:输入一段话,统计每个英文字母出现的次数。

sentence = input('请输入一段话: ') counter = {} for ch in sentence: if 'A' int: """求最大公约数和最小公倍数""" a, b = x, y while b % a != 0: a, b = b % a, a return a, x * y // a

代码二:

def gcd(x: int, y: int) -> int: """求最大公约数""" while y % x != 0: x, y = y % x, x return x def lcm(x: int, y: int) -> int: """求最小公倍数""" return x * y // gcd(x, y)思考:请比较上面的代码一和代码二,想想哪种做法是更好的选择。案例5:写出计算一组样本数据描述性统计信息的函数。import math def ptp(data): """求极差(全距)""" return max(data) - min(data) def average(data): """求均值""" return sum(data) / len(data) def variance(data): """求方差""" x_bar = average(data) temp = [(num - x_bar) ** 2 for num in data] return sum(temp) / (len(temp) - 1) def standard_deviation(data): """求标准差""" return math.sqrt(variance(data)) def median(data): """找中位数""" temp, size = sorted(data), len(data) if size % 2 != 0: return temp[size // 2] else: return average(temp[size // 2 - 1:size // 2 + 1])第15课:函数使用进阶

前面我们讲到了关于函数的知识,我们还讲到过Python中常用的数据类型,这些类型的变量都可以作为函数的参数或返回值,用好函数还可以让我们做更多的事情。

关键字参数

下面是一个判断传入的三条边长能否构成三角形的函数,在调用函数传入参数时,我们可以指定参数名,也可以不指定参数名,代码如下所示。

def is_triangle(a, b, c): print(f'a = {a}, b = {b}, c = {c}') return a + b > c and b + c > a and a + c > b # 调用函数传入参数不指定参数名按位置对号入座 print(is_triangle(1, 2, 3)) # 调用函数通过“参数名=参数值”的形式按顺序传入参数 print(is_triangle(a=1, b=2, c=3)) # 调用函数通过“参数名=参数值”的形式不按顺序传入参数 print(is_triangle(c=3, a=1, b=2))

在没有特殊处理的情况下,函数的参数都是位置参数,也就意味着传入参数的时候对号入座即可,如上面代码的第7行所示,传入的参数值1、2、3会依次赋值给参数a、b、c。当然,也可以通过参数名=参数值的方式传入函数所需的参数,因为指定了参数名,传入参数的顺序可以进行调整,如上面代码的第9行和第11行所示。

调用函数时,如果希望函数的调用者必须以参数名=参数值的方式传参,可以用命名关键字参数(keyword-only argument)取代位置参数。所谓命名关键字参数,是在函数的参数列表中,写在*之后的参数,代码如下所示。

def is_triangle(*, a, b, c): print(f'a = {a}, b = {b}, c = {c}') return a + b > c and b + c > a and a + c > b #如果执行:is_triangle(3,4,5),会提示: # TypeError: is_triangle() takes 0 positional arguments but 3 were given # print(is_triangle(3, 4, 5)) # 传参时必须使用“参数名=参数值”的方式,位置不重要 print(is_triangle(a=3, b=4, c=5)) print(is_triangle(c=5, b=4, a=3))注意:上面的is_triangle函数,参数列表中的*是一个分隔符,*前面的参数都是位置参数,而*后面的参数就是命名关键字参数。

我们之前讲过在函数的参数列表中可以使用可变参数*args来接收任意数量的参数,但是我们需要看看,*args是否能够接收带参数名的参数。

def calc(*args): result = 0 for arg in args: if type(arg) in (int, float): result += arg return result print(calc(a=1, b=2, c=3))

执行上面的代码会引发TypeError错误,错误消息为calc() got an unexpected keyword argument 'a',由此可见,*args并不能处理带参数名的参数。我们在设计函数时,如果既不知道调用者会传入的参数个数,也不知道调用者会不会指定参数名,那么同时使用可变参数和关键字参数。关键字参数会将传入的带参数名的参数组装成一个字典,参数名就是字典中键值对的键,而参数值就是字典中键值对的值,代码如下所示。

def calc(*args, **kwargs): result = 0 for arg in args: if type(arg) in (int, float): result += arg for value in kwargs.values(): if type(value) in (int, float): result += value return result print(calc()) # 0 print(calc(1, 2, 3)) # 6 print(calc(a=1, b=2, c=3)) # 6 print(calc(1, 2, c=3, d=4)) # 10提示不带参数名的参数(位置参数)必须出现在带参数名的参数(关键字参数)之前,否则将会引发异常。例如,执行calc(1, 2, c=3, d=4, 5)将会引发SyntaxError错误,错误消息为positional argument follows keyword argument,翻译成中文意思是“位置参数出现在关键字参数之后”。高阶函数的用法

函数的参数和返回值可以是任意类型的对象,这就意味着函数本身也可以作为函数的参数或返回值,这就是所谓的高阶函数

如果我们希望上面的calc函数不仅仅可以做多个参数求和,还可以做多个参数求乘积甚至更多的二元运算,我们就可以使用高阶函数的方式来改写上面的代码,将加法运算从函数中移除掉,具体的做法如下所示。

def calc(*args, init_value, op, **kwargs): result = init_value for arg in args: if type(arg) in (int, float): result = op(result, arg) for value in kwargs.values(): if type(value) in (int, float): result = op(result, value) return result

注意,上面的函数增加了两个参数,其中init_value代表运算的初始值,op代表二元运算函数。经过改造的calc函数不仅仅可以实现多个参数的累加求和,也可以实现多个参数的累乘运算,代码如下所示。

def add(x, y): return x + y def mul(x, y): return x * y print(calc(1, 2, 3, init_value=0, op=add, x=4, y=5)) # 15 print(calc(1, 2, x=3, y=4, z=5, init_value=1, op=mul)) # 120

Python内置函数中有不少高阶函数,我们前面提到过的filter和map函数就是高阶函数,前者可以实现对序列中元素的过滤,后者可以实现对序列中元素的映射,例如我们要去掉一个整数列表中的奇数,并对所有的偶数求平方得到一个新的列表,就可以直接使用这两个函数来做到,具体的做法是如下所示。

def is_even(num): return num % 2 == 0 def square(num): return num ** 2 numbers1 = [35, 12, 8, 99, 60, 52] numbers2 = list(map(square, filter(is_even, numbers1))) print(numbers2) # [144, 64, 3600, 2704]

当然,要完成上面代码的功能,也可以使用列表生成式,列表生成式的做法更为简单优雅。

numbers1 = [35, 12, 8, 99, 60, 52] numbers2 = [num ** 2 for num in numbers1 if num % 2 == 0] print(numbers2) # [144, 64, 3600, 2704]Lambda函数

在使用高阶函数的时候,如果作为参数或者返回值的函数本身非常简单,一行代码就能够完成,那么我们可以使用Lambda函数来表示。Python中的Lambda函数是没有的名字函数,所以很多人也把它叫做匿名函数,匿名函数只能有一行代码,代码中的表达式产生的运算结果就是这个匿名函数的返回值。上面代码中的is_even和square函数都只有一行代码,我们可以用Lambda函数来替换掉它们,代码如下所示。

numbers1 = [35, 12, 8, 99, 60, 52] numbers2 = list(map(lambda x: x ** 2, filter(lambda x: x % 2 == 0, numbers1))) print(numbers2) # [144, 64, 3600, 2704]

通过上面的代码可以看出,定义Lambda函数的关键字是lambda,后面跟函数的参数,如果有多个参数用逗号进行分隔;冒号后面的部分就是函数的执行体,通常是一个表达式,表达式的运算结果就是Lambda函数的返回值,不需要写return 关键字。

如果需要使用加减乘除这种简单的二元函数,也可以用Lambda函数来书写,例如调用上面的calc函数时,可以通过传入Lambda函数来作为op参数的参数值。当然,op参数也可以有默认值,例如我们可以用一个代表加法运算的Lambda函数来作为op参数的默认值。

def calc(*args, init_value=0, op=lambda x, y: x + y, **kwargs): result = init_value for arg in args: if type(arg) in (int, float): result = op(result, arg) for value in kwargs.values(): if type(value) in (int, float): result = op(result, value) return result # 调用calc函数,使用init_value和op的默认值 print(calc(1, 2, 3, x=4, y=5)) # 15 # 调用calc函数,通过lambda函数给op参数赋值 print(calc(1, 2, 3, x=4, y=5, init_value=1, op=lambda x, y: x * y)) # 120提示:注意上面的代码中的calc函数,它同时使用了可变参数、关键字参数、命名关键字参数,其中命名关键字参数要放在可变参数和关键字参数之间,传参时先传入可变参数,关键字参数和命名关键字参数的先后顺序并不重要。

有很多函数在Python中用一行代码就能实现,我们可以用Lambda函数来定义这些函数,调用Lambda函数就跟调用普通函数一样,代码如下所示。

import operator, functools # 一行代码定义求阶乘的函数 fac = lambda num: functools.reduce(operator.mul, range(1, num + 1), 1) # 一行代码定义判断素数的函数 is_prime = lambda x: x > 1 and all(map(lambda f: x % f, range(2, int(x ** 0.5) + 1))) # 调用Lambda函数 print(fac(10)) # 3628800 print(is_prime(9)) # False提示1:上面使用的reduce函数是Python标准库functools模块中的函数,它可以实现对数据的归约操作,通常情况下,过滤(filter)、映射(map)和归约(reduce)是处理数据中非常关键的三个步骤,而Python的标准库也提供了对这三个操作的支持。 提示2:上面使用的all函数是Python内置函数,如果传入的序列中所有布尔值都是True,all函数就返回True,否则all函数就返回False。简单的总结

Python中的函数可以使用可变参数*args和关键字参数**kwargs来接收任意数量的参数,而且传入参数时可以带上参数名也可以没有参数名,可变参数会被处理成一个元组,而关键字参数会被处理成一个字典。Python中的函数是一等函数,可以赋值给变量,也可以作为函数的参数和返回值,这也就意味着我们可以在Python中使用高阶函数。如果我们要定义的函数非常简单,只有一行代码且不需要函数名,可以使用Lambda函数(匿名函数)。

TIPS1:分数符号(Latex)

\tfrac 设置分数为 textstyle $ \tfrac {1}{2} $ 代码为: \tfrac 空格 {1}{2},前后加$,字体有缩放

\dfrac 设置分数为 displaystyle 单行模式,与行内字体高度一致 $ \dfrac {1}{2} $

\frac 根据上下文决定使用 \tfrac 还是 \dfrac

\cfrac 用于表示连续分数 $ \cfrac{2}{1+\cfrac{2}{1+\cfrac{2}{1}}}$ 代码为: \cfrac{2}{1+\cfrac{2}{1+\cfrac{2}{1}}}

$ x_1 , x^2 $ 的代码分别为: x_1 , x^2 前后加$

TIPS2:String库import string ascii = string.ascii_letters print(ascii) #abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ ascii_lower= string.ascii_lowercase print(ascii_lower) #abcdefghijklmnopqrstuvwxyz ascii_upper= string.ascii_uppercase print(ascii_upper) #ABCDEFGHIJKLMNOPQRSTUVWXYZ digits = string.digits print(digits) #0123456789 hexdigits= string.hexdigits print(hexdigits) #0123456789abcdefABCDEF printable = string.printable print(printable) #0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&'()*+,-./:;?@[\]^_`{|}~

参数为:

TIPS3:operator库TIPS4:处理数据三步骤

过滤(filter)、映射(map)和归约(reduce) 摘自:https://www.runoob.com/

过滤(filter)

用于过滤序列,过滤掉不符合条件的元素,返回一个迭代器对象,如果要转换为列表,可以使用 list() 来转换。 过滤出1~100中平方根是整数的数:

import math def is_sqr(x): return math.sqrt(x) % 1 == 0

tmplist = filter(is_sqr, range(1, 101)) newlist = list(tmplist) print(newlist) 输出结果 : [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

映射(map)根据提供的函数对指定序列做映射。 >>> def square(x) : # 计算平方数 return x ** 2 >>> map(square, [1,2,3,4,5]) # 计算列表各个元素的平方 # 返回迭代器 >>> list(map(square, [1,2,3,4,5])) # 使用 list() 转换为列表 [1, 4, 9, 16, 25] >>> list(map(lambda x: x ** 2, [1, 2, 3, 4, 5])) # 使用 lambda 匿名函数 [1, 4, 9, 16, 25]

归约(reduce)

reduce() 函数会对参数序列中元素进行累积。

函数将一个数据集合(链表,元组等)中的所有数据进行下列操作:用传给 reduce 中的函数 function(有两个参数)先对集合中的第 1、2 个元素进行操作,得到的结果再与第三个数据用 function 函数运算,最后得到一个结果。

注意:Python3.x reduce() 已经被移到 functools 模块里,如果我们要使用,需要引入 functools 模块来调用 reduce() 函数:

from functools import reduce

参数 function -- 函数,有两个参数 iterable -- 可迭代对象 initializer -- 可选,初始参数

from functools import reduce def add(x, y) : # 两数相加 return x + y sum1 = reduce(add, [1,2,3,4,5]) # 计算列表和:1+2+3+4+5 sum2 = reduce(lambda x, y: x+y, [1,2,3,4,5]) # 使用 lambda 匿名函数 print(sum1) #15 print(sum2) #15

如果文章对您有帮助,请加@打酱油的工程师关注,点赞支持我的持续创作!



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3